package edu.hawaii.myisern.action;

import java.util.Iterator;
import edu.hawaii.myisern.model.MyIsernModel;
import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.DontValidate;
import net.sourceforge.stripes.action.RedirectResolution;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.action.ActionBean;
import net.sourceforge.stripes.action.ActionBeanContext;
import net.sourceforge.stripes.validation.SimpleError;
import net.sourceforge.stripes.validation.Validate;
import net.sourceforge.stripes.validation.ValidationErrors;
import edu.hawaii.myisern.researchers.jaxb.Researcher;

/**
 * Provides a web interface for researcher actions.
 * 
 * @author Edward Kim
 * @author JianFei Liao
 * @author KaYee Leung
 */
public class ResearchersActionBean implements ActionBean {

  /** The name for the researcher. */
  @Validate(field = "researcherName") private String researcherName;
  /** The Researcher object instance. */
  private Researcher researcher;
  /** An invalid organization link relates to the researcher. */
  private String linkMessage;
  
  /** Required by the ActionBean interface. */
  private ActionBeanContext context;
  /** Our single MyIsernModel instance manipulated by all webapp users. */
  private MyIsernModel myModel = MyIsernModel.getInstance();
  
  /**
   * Returns the context. Required by the interface.
   * 
   * @return the ActionBeanContext.
   */
  public ActionBeanContext getContext() {
    return context;
  }

  /**
   * Sets the context. Required by the interface.
   * 
   * @param context The ActionBeanContext to set.
   */
  public void setContext(ActionBeanContext context) {
    this.context = context;
  }

  /**
   * Returns a researcher.
   * 
   * @return A researcher.
   */
  public Researcher getResearcher() {
    return this.researcher;
  }
  
  /**
   * Sets a researcher.
   * 
   * @param researcher The researcher that will be set to.
   */
  public void setResearcher(Researcher researcher) {
    this.researcher = researcher;
  }

  /**
   * Sets the researcher's name.
   * 
   * @param name The researcher name to set.
   */
  public void setResearcherName(String name) {
    this.researcherName = name;
  }
  
  /**
   * Sets the invalid organization link.
   * 
   * @param string The new invalid organization link.
   */
  public void setLinkMessage(String string) {
    this.linkMessage = string;
  }
  
  /**
   * Provides an iterator over the researchers to the page.
   * 
   * @exception Exception If error occur.
   * @return an iterator that will go through all the researchers
   */
  public Iterator<Researcher> getResearchersIterator() throws Exception {
    return this.myModel.getResearchersList().iterator();
  }
  
  /**
   * Show information for all researchers.
   * 
   * @return A Resolution indicating to redisplay the researchers.jsp pagse.
   * @throws Exception error message
   */
  public Resolution showAllResearchers() throws Exception {
    return new RedirectResolution("/researchers.jsp").flash(this);
  }


  /**
   * Populates the data for the research before editing.
   * 
   * @return A resolution to the editResearcher page.
   */
  @DontValidate
  public Resolution preEditResearcher() {
    this.researcher = this.myModel
        .getSingleResearcher(this.researcherName.trim().replace(' ', '_'));
    return new RedirectResolution("/editResearcher.jsp").flash(this);
  }    
  
  /**
   * Saves the changes for researcher.
   * 
   * @throws Exception exception  
   * @return A new resolution for the researcher page.
   */
  @DefaultHandler
  public Resolution saveReseacher() throws Exception {
    ValidationErrors errors = new ValidationErrors();
    // check if the researcher name is provided
    if (this.researcher == null || this.researcher.getName() == null) {
      errors.add("nullResearcher", new SimpleError("The researcher name is required."));
      this.getContext().setValidationErrors(errors);
      return this.getContext().getSourcePageResolution();
    }
    // check the other data
    if (this.researcher.getEmail() == null) {
      this.researcher.setEmail("");
    }
    if (this.researcher.getOrganization() == null) {
      this.researcher.setOrganization("");
    }
    if (this.researcher.getPictureLink() == null) {
      this.researcher.setPictureLink("");
    }
    if (this.researcher.getBioStatement() == null) {
      this.researcher.setBioStatement("");
    }
    // store the change and write out to XML file
    this.myModel.addOrEditResearcher(this.researcher);
    this.myModel.save();
    return new RedirectResolution("/researchers.jsp").flash(this);
  }

  /**
   * Finds the researcher that has the invalid organization link.
   *
   * @return A new resolution of the editResearcher page.
   */
  public Resolution findResearcherWithLink() {
    // pass the link message to find the researcher
    int index = this.linkMessage.indexOf(':');
    String name = this.linkMessage.substring(index + 1).trim();
    String id = name.replace(' ', '_');
    this.researcher = this.myModel.getResearchersMap().get(id);
    return new RedirectResolution("/editResearcher.jsp").flash(this);
  }  
}